package com.googlecode.archimedes.filegen.template;

import java.text.MessageFormat;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * The Template class encapsulates the details around a template. 
 * It is used by the underlying generation functions to determine what
 * engine-specific templates to execute.
 * 
 * @author John Lema, Erik Gustavson
 * @version $Id: Template.java 2820 2006-08-22 18:44:06 +0000 (Tue, 22 Aug 2006) erik $
 */
public class Template {

    private Log                logger           = LogFactory.getLog(this.getClass().getName());

    private String             extension        = "";                                          //.java, .do, .jsp, .whatever
    private String             templateName     = "";                                          //the "Action" in "Action.vm" and CustomerAction.java
    private String             outputPath       = "";                                          //relative /yomomma/web-inf/foo/etc "
    private Class              allowedAssetType = null;                                        //what kind of Asset this template operates on.
    private String             fileName         = "{0}";
    private String             format           = CAPFIRST;
    private boolean            abstractAllowed  = false;

    public static final String UPPER            = "upper";
    public static final String LOWER            = "lower";
    public static final String CAMEL            = "camel";
    public static final String CAPFIRST         = "capfirst";

    public Template() {
        super();
    }

    /**
     * @return where do you want the file to go? "c://Windows//yomomma//"?
     */
    public String getOutputPath() {
        return outputPath;
    }

    /**
     * @param outputPath
     *            where do you want the file to go? "c://Windows//yomomma//"?
     */
    public void setOutputPath(String outputPath) {
        this.outputPath = outputPath;
    }

    /**
     * @return .java, .do, .jsp, .whatever
     */
    public String getExtension() {
        return extension;
    }

    /**
     * @param extension
     *            .java, .do, .jsp, .whatever
     */
    public void setExtension(String extension) {
        this.extension = extension;
    }

    /**
     * @return the "Action" in "Action.vm" and CustomerAction.java
     */
    public String getTemplateName() {
        return templateName;
    }

    /**
     * @param extension
     *            the "Action" in "Action.vm" and CustomerAction.java
     */
    public void setTemplateName(String templateName) {
        this.templateName = templateName;
    }

    /**
     * Output the TemplateFile as a string
     * 
     * @see java.lang.Object#toString()
     */
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("TemplatePath [" + this.getOutputPath() + "] ");
        sb.append("TemplateName [" + this.getTemplateName() + "] ");
        sb.append("Extension [" + this.getExtension() + "] ");
        sb.append("Type [" + this.getAllowedAsset() + "] ");
        return sb.toString();
    }

    /**
     * Used by the templating system to determine which asset types this template is applied to.
     * 
     * @return a Class representing the allowed Asset type
     */
    public Class getAllowedAssetClass() {
        return allowedAssetType;
    }

    /**
     * Used by the templating system to determine which asset types this template is applied to.
     * 
     * @param allowedAssetType
     *            The Class of the Asset this template operates on
     */
    public void setAllowedAssetClass(Class allowedAssetType) {
        this.allowedAssetType = allowedAssetType;
    }

    /**
     * Used by the templating system to determine which asset types this template is applied to.
     * 
     * @param allowedAssetType
     *            A String representing the fully-qualified classname of the Asset this template operates on
     */
    public void setAllowedAsset(String allowedAssetType) throws ClassNotFoundException {
        Class assetType = Class.forName(allowedAssetType);
        this.allowedAssetType = assetType;
    }

    public String getAllowedAsset() {
        return this.allowedAssetType != null ? allowedAssetType.getName() : "[undefined]";
    }

    /**
     * Returns the capitalization.
     *
     * @return String value of capitalization
     */
    public String getFormat() {
        return format;
    }

    /**
     * Sets the capitalization
     * @param capitalization The capitalization to set.
     */
    public void setFormat(String format) {
        this.format = format;
    }

    /**
     * Returns the fileName.
     *
     * @return String value of fileName
     */
    public String getFileName() {
        return fileName;
    }

    /**
     * Sets the fileName
     * @param fileName The fileName to set.
     */
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    /**
     * Returns the abstractAllowed.
     *
     * @return boolean value of abstractAllowed
     */
    public boolean isAbstractAllowed() {
        return abstractAllowed;
    }

    /**
     * Sets the abstractAllowed
     * @param abstractAllowed The abstractAllowed to set.
     */
    public void setAbstractAllowed(boolean abstractAllowed) {
        this.abstractAllowed = abstractAllowed;
    }

    /**
     * Returns a properly formated filename
     * 
     * @param args
     * @return
     */
    public String resolveFileName(Object[] args) {
        String result = MessageFormat.format(getFileName(), args);

        if (this.getFormat().equals(CAPFIRST)) {
            result = result.substring(0, 1).toUpperCase() + result.substring(1);
        } else if (this.getFormat().equals(UPPER)) {
            result = result.toUpperCase();
        } else if (this.getFormat().equals(LOWER)) {
            result = result.toLowerCase();
        } else if (this.getFormat().equals(CAMEL)) {
            result = result.substring(0, 1).toLowerCase() + result.substring(1);
        }

        return result;
    }
}